package com.apes.fn.scm.purchaseReturn.service;



import com.alibaba.fastjson.JSONObject;
import com.apes.fn.scm.crossCompany.transfer.model.CrossCompanyTransferItemNew;
import com.apes.fn.scm.crossCompany.transfer.model.CrossCompanyTransferNew;
import com.apes.fn.scm.crossCompany.transfer.model.PrintRecord;
import com.apes.fn.scm.crossCompany.transfer.repository.PrintRecordRepository;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfter;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfterJunior;
import com.apes.fn.scm.purchaseReturn.model.PurchaseAfterJuniorItem;
import com.apes.fn.scm.purchaseReturn.repository.PurchaseAfterJuniorRepository;
import com.apes.fn.scm.purchaseReturn.repository.PurchaseAfterRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.soe.store.database.repository.BusinessTypeRepository;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.ledger.model.Ledger;
import com.apes.scm.account.ledger.repository.LedgerRepository;
import com.apes.scm.account.method.Batch;
import com.apes.scm.account.method.BatchMethod;
import com.apes.scm.account.transit.DepositInTransitService;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.rbac.model.User;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.PickItem;
import com.apes.scm.stock.transfer.repository.PickRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherService;
import com.apes.scm.voucher.service.VoucherType;
import com.apes.scm.voucher.service.builder.CrossTransferVoucherBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static java.lang.Math.abs;
import static java.util.stream.Collectors.groupingBy;

/**
 * @BelongsProject: apes-server
 * @BelongsPackage: com.apes.fn.scm.purchaseReturn.service
 * @ClassName: PurchaseAfterJuniorService
 * @Author: ljp
 * @CreateTime: 2021-01-19 14:49
 * @Description: 售后工单服务
 * @Version: 1.0
 */
@Service("purchaseAfterJuniorService")
public class PurchaseAfterJuniorService extends DomainService {
    @Autowired
    private PurchaseAfterJuniorRepository purchaseAfterJuniorRepository;

    @Autowired
    private LocationRepository locationRepository;

    @Autowired
    ApesLoggerService apesLoggerService;

    @Autowired
    private PickRepository pickRepository;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private ProductAccountService productAccountService;

    @Autowired
    private LedgerRepository ledgerRepository;

    /**
     * 驳回
     * @param request
     * @return
     */
    public PurchaseAfterJunior pending(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        check(purchaseAfterJunior);
        if (!"apply".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是申请状态，无法驳回");

        purchaseAfterJunior.setRejectUid(request.getPerson());
        purchaseAfterJunior.setRejectDate(new Date());
        purchaseAfterJunior.setState("pending");
        return purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }
    /**
     * 同意
     * @param request
     * @return
     */
    public PurchaseAfterJunior consent(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        checkQty(purchaseAfterJunior);
        if (!"apply".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是申请状态，无法同意");

        createPurchaseAfterJunior(purchaseAfterJunior,"售后工单部分同意拆单");//拆单
        refreshQty(purchaseAfterJunior);//更新数量

        Location receipt = locationRepository.findlocationByCompany(purchaseAfterJunior.getCompany().getId());
        if (receipt == null) throw new RuntimeException("找不到该门店["+purchaseAfterJunior.getLocation().getDept().getId() +"]有效的退货周转仓");

        createPickOrder(purchaseAfterJunior,purchaseAfterJunior.getLocation(),receipt,null,true,"售后工单同意");//创建发货单

        purchaseAfterJunior.setConsentUid(request.getPerson());
        purchaseAfterJunior.setConsentDate(new Date());
        purchaseAfterJunior.setState("deliver");
        purchaseAfterJunior =  purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
        return hide(purchaseAfterJunior);
    }

    /**
     * 退回
     * @param request
     * @return
     */
    public PurchaseAfterJunior sendBack(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        checkQty(purchaseAfterJunior);
        if (!"identify".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待鉴定状态，无法退回");

        Location ship = locationRepository.findlocationByCompany(purchaseAfterJunior.getCompany().getId());
        Location receipt = purchaseAfterJunior.getLocation();
        if(Objects.isNull(ship)) throw new RuntimeException("[" + receipt.getId() + "]" + receipt.getName() + "退货周转仓已被取消有效标记，如需继续流程请联系相关人员开启");
        createPickOrder(purchaseAfterJunior,ship,purchaseAfterJunior.getLocation(),null,true,"售后工单退回");
        createPurchaseAfterJunior(purchaseAfterJunior,"售后工单部分退回");
        refreshQty(purchaseAfterJunior);

        purchaseAfterJunior.setBackUid(request.getPerson());
        purchaseAfterJunior.setBackDate(new Date());
        purchaseAfterJunior.setState("backDeli");

        purchaseAfterJunior =  purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
        return hide(purchaseAfterJunior);
    }

    /**
     * 返厂
     * @param request
     * @return
     */
    public PurchaseAfterJunior revert(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        checkQty(purchaseAfterJunior);
        if (!"identify".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待鉴定状态，无法返厂");

        createPurchaseAfterJunior(purchaseAfterJunior,"售后工单部分返厂拆单");
        refreshQty(purchaseAfterJunior);

        double money = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e -> e.getReturnQty() > 0).mapToDouble(e -> e.getReturnQty() * e.getPriceUnit()).sum();
        //原始供应商
        PartyRole supplier = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().map(e -> e.getSupplier()).collect(Collectors.toList()).get(0);
        if (checkCompany(purchaseAfterJunior.getCompany(),supplier,money)) {
            purchaseAfterJunior.setState("revert");
            Location ship = locationRepository.findlocationByCompany(purchaseAfterJunior.getCompany().getId());
            createPickOrder(purchaseAfterJunior,ship,null,supplier,true,"售后工单返厂");
        }else {
            purchaseAfterJunior.setState("finance");
            String str = purchaseAfterJunior.getNote()==null?"待财务审核":purchaseAfterJunior.getNote()+ "--" + "待财务审核";
            purchaseAfterJunior.setNote(str);
        }

        purchaseAfterJunior.setApproveUid(request.getPerson());
        purchaseAfterJunior =  purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
        return hide(purchaseAfterJunior);
    }

    /**
     * 撤销
     * @param request
     * @return
     */
    public PurchaseAfterJunior repeal(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        purchaseAfterJunior = check(purchaseAfterJunior);
        if (!"deliver;pending".contains(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待发货/待处理状态，无法撤销");

        if ("deliver".equals(purchaseAfterJunior.getState())) {
            //取消交货单
            JSONObject tempJson = new JSONObject();
            tempJson.put("operation","deliver");
            List<Map> items = this.makeupPick(tempJson, purchaseAfterJunior);
            tempJson.put("items", items);
            invoke("stock.pick.cancel", tempJson);

        }
        updateReturnQty(purchaseAfterJunior,false,"售后工单撤销");

        purchaseAfterJunior.setRepealUid(request.getPerson());
        purchaseAfterJunior.setRepealDate(new Date());
        purchaseAfterJunior.setState("done");
        return purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    /**
     * 转申请
     * @param request
     * @return
     */
    public PurchaseAfterJunior apply(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        purchaseAfterJunior = check(purchaseAfterJunior);
        if (!"pending".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待处理状态，无法转申请");

        purchaseAfterJunior.setState("apply");
        return purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    /**
     * 审批
     * @param request
     * @return
     */
    public PurchaseAfterJunior approve(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        purchaseAfterJunior = check(purchaseAfterJunior);
        if (!"finance".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待财务审批状态，无法审批");

        purchaseAfterJunior.setState("revert");
        Location ship = locationRepository.findlocationByCompany(purchaseAfterJunior.getCompany().getId());
        Location receipt = purchaseAfterJunior.getLocation();
        if (!receipt.isValid() || Objects.isNull(ship)) throw new RuntimeException("[" + receipt.getId() + "]" + receipt.getName() + "退货周转仓已被取消有效标记，如需继续流程请联系相关人员开启");
        PartyRole supplier = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().map(e -> e.getSupplier()).collect(Collectors.toList()).get(0);
        createPickOrder(purchaseAfterJunior,ship,null,supplier,true,"售后工单返厂");

        purchaseAfterJunior.setApproveUid(request.getPerson());
        purchaseAfterJunior.setApproveDate(new Date());
        return purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    /**
     * 拒绝
     * @param request
     * @return
     */
    public PurchaseAfterJunior refuse(SimpleRequest request) {
        PurchaseAfterJunior purchaseAfterJunior = request.getO(PurchaseAfterJunior.class);
        purchaseAfterJunior = check(purchaseAfterJunior);
        if (!"finance".equals(purchaseAfterJunior.getState())) throw new RuntimeException("该售后单不是待财务审批状态，无法拒绝");
        Location receipt = purchaseAfterJunior.getLocation();
        if (!receipt.isValid()) throw new RuntimeException("[" + receipt.getId() + "]" + receipt.getName() + "退货周转仓已被取消有效标记，如需继续流程请联系相关人员开启");

        purchaseAfterJunior.setRefuseUid(request.getPerson());
        purchaseAfterJunior.setRefuseDate(new Date());
        purchaseAfterJunior.setState("identify");
        return purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    public PurchaseAfterJunior check(PurchaseAfterJunior purchaseAfterJunior) {
        PurchaseAfterJunior purchaseAfterJuniorNew = purchaseAfterJuniorRepository.findOne(purchaseAfterJunior.getId());
        if (purchaseAfterJuniorNew == null) throw new RuntimeException("找不到该售后工单");
        return purchaseAfterJuniorNew;
    }


    /**
     * 创建发/收货单
     */
    private Pick createPickOrder(PurchaseAfterJunior purchaseAfterJunior, Location ship,Location receipt,PartyRole supplier,boolean isDeliver,String note) {
        //创建拣配单
        Pick pick = new Pick();
        com.apes.scm.masterdata.enumeration.model.Enumeration enumeration = new Enumeration();
        enumeration.setId("one");
        //部分交货
        pick.setMoveType(enumeration);
        pick.setNote(note);
        // 公司为发货仓的公司
        pick.setCompany(purchaseAfterJunior.getCompany());
        pick.setPartner(supplier==null?purchaseAfterJunior.getCompany():supplier);
        //合作伙伴为收货仓的公司
        pick.setLocation(ship);
        pick.setReceiptLocation(receipt);
        pick.setOrigin(purchaseAfterJunior.getId());
        pick.setOriginBusinessType(purchaseAfterJunior.getInnerBusinessType());
        // 交货类型： 交货
        pick.setOperation(isDeliver?"deliver":"receipt");
        pick.setPickItems(getPickItem(purchaseAfterJunior));
        // 创建交货单
        EventUtil.sendSynEvent(this, "event:stock.pick.save", pick);
        return pick;
    }

    private Set<PickItem> getPickItem(PurchaseAfterJunior purchaseAfterJunior) {
        List<PurchaseAfterJuniorItem> items = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e -> e.getReturnQty() > 0).collect(Collectors.toList());
        Set<PickItem> pickItems = items.stream().map(
                (PurchaseAfterJuniorItem item) -> {
                    PickItem pickItem = new PickItem();
                    pickItem.setProduct(item.getProduct());
                    pickItem.setUom(item.getUom());
                    pickItem.setOrderedQty(item.getReturnQty());
                    pickItem.setProductUomQty(item.getReturnQty());
                    pickItem.setOriginLine(item.getId());
                    return pickItem;
                }).collect(Collectors.toSet());
        return pickItems;
    }

    /**
     * 创建售后工单
     */
    public void createPurchaseAfterJunior(PurchaseAfterJunior olePurchaseAfterJunior,String note) {
        String json = JSONObject.toJSONString(olePurchaseAfterJunior);
        PurchaseAfterJunior purchaseAfterJunior = JSONObject.parseObject(json, PurchaseAfterJunior.class);
        purchaseAfterJunior.setId(null);
        String str = purchaseAfterJunior.getNote()==null?note:purchaseAfterJunior.getNote()+ "--" + note;
        purchaseAfterJunior.setNote(str);

        Set<PurchaseAfterJuniorItem> items = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e -> e.getProductQty() != e.getReturnQty()).collect(Collectors.toSet());
        if (items.size()==0) return;
        items.forEach(item-> {
            item.setId(null);
            item.setProductQty(item.getProductQty()-item.getReturnQty());
            item.setReturnQty(item.getProductQty());
        });
        purchaseAfterJunior.setPurchaseAfterJuniorItems(items);
        purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    public void updateReturnQty(PurchaseAfterJunior purchaseAfterJunior,boolean flag,String note) {
        purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e->e.getReturnQty()>0).forEach(item->{
            double productAccountQty = flag?-1*item.getReturnQty():item.getReturnQty();
            double inventoryQty = flag?item.getReturnQty():-1*item.getReturnQty();
            // 减少（增加）商品可用数
            productAccountService.setProductAvailable(item.getProduct(), purchaseAfterJunior.getLocation(),
                    item.getUom(), productAccountQty, purchaseAfterJunior.getInnerBusinessType(), purchaseAfterJunior.getId(),
                    item.getId(), note, purchaseAfterJunior.getCompany());
            //减少（增加）商品批次冻结数
            inventoryService.changeFrostQty(item.getInventoryBatch(), item.getUom(), inventoryQty, purchaseAfterJunior.getCompany(),
                    purchaseAfterJunior.getInnerBusinessType(), purchaseAfterJunior.getId(),
                    item.getId(), note);
        });
    }

    @Listener(topic = "event:stock.pick.delivery")
    private void willWrite(SimpleRequest request) {
        JSONObject param = request.getJO();
        if (!param.getString("originBusinessType").equals(PurchaseAfterJunior.class.getSimpleName())) return;
        String pickId = param.getString("pickId");
        if (pickId == null) return;
        Pick pick = pickRepository.findOne(pickId);
        PurchaseAfterJunior purchaseAfterJunior = purchaseAfterJuniorRepository.findOne(pick.getOrigin());
        if (purchaseAfterJunior == null) return;
        if ("deliver".equals(pick.getOperation())) {//交货单发货
            if ("deliver".equals(purchaseAfterJunior.getState())) {//待发货
                purchaseAfterJunior.setState("receipt");
                createPickOrder(purchaseAfterJunior,pick.getReceiptLocation(),pick.getLocation(),null,false,"售后工单同意");
                this.deleteDepositInTransit(purchaseAfterJunior);
            }else if ("backDeli".equals(purchaseAfterJunior.getState())){//待退回发货
                purchaseAfterJunior.setState("backRece");
                createPickOrder(purchaseAfterJunior,pick.getReceiptLocation(),pick.getLocation(),null,false,"售后工单退回");
            }else if("revert".equals(purchaseAfterJunior.getState())) {//待返厂发货
                purchaseAfterJunior.setState("done");
                createVoucher(pick,purchaseAfterJunior);
            }
        }else {//交货单收货
            if ("receipt".equals(purchaseAfterJunior.getState())) {//待收货
                purchaseAfterJunior.setState("identify");
                updateQty(purchaseAfterJunior,"售后工单退回可用数不变");
            }else if ("backRece".equals(purchaseAfterJunior.getState())) {//待退回收货
                purchaseAfterJunior.setState("done");
                updateInventoryQty(purchaseAfterJunior,"售后工单退回");
            }
        }
        purchaseAfterJuniorRepository.saveAndFlush(purchaseAfterJunior);
    }

    public void deleteDepositInTransit(PurchaseAfterJunior purchaseAfterJunior) {
        PurchaseAfter purchaseAfter = SpringManager.getBean(PurchaseAfterRepository.class).findOne(purchaseAfterJunior.getSource());
        DepositInTransitService depositInTransitService = SpringManager.getBean(DepositInTransitService.class);
        purchaseAfterJunior.getPurchaseAfterJuniorItems().forEach(item -> {
            purchaseAfter.getPurchaseAfterItems().forEach(afterItem -> {
                if (item.getInventoryBatch().getId() == afterItem.getInventoryBatch().getId()) {
                    depositInTransitService.delete("PurchaseAfter", purchaseAfterJunior.getSource(),
                            afterItem.getId(), purchaseAfterJunior.getLocation());
                }
            });

        });
    }


    public void updateQty(PurchaseAfterJunior purchaseAfterJunior,String note) {
        Location location = locationRepository.findlocationByCompany(purchaseAfterJunior.getCompany().getId());
        if (location == null) throw new RuntimeException("未找到有效退货周转仓，请检查仓库主数据");
        purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e->e.getReturnQty()>0).forEach(item->{
            // 减少商品可用数
            productAccountService.setProductAvailable(item.getProduct(), location,
                    item.getUom(), -1*item.getReturnQty(), purchaseAfterJunior.getInnerBusinessType(), purchaseAfterJunior.getId(),
                    item.getId(), note, purchaseAfterJunior.getCompany());
        });
    }

    public void updateInventoryQty(PurchaseAfterJunior purchaseAfterJunior,String note) {
        purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(e->e.getReturnQty()>0).forEach(item->{
            //减少商品批次冻结数
            inventoryService.changeFrostQty(item.getInventoryBatch(), item.getUom(), -1*item.getReturnQty(), purchaseAfterJunior.getCompany(),
                    purchaseAfterJunior.getInnerBusinessType(), purchaseAfterJunior.getId(),
                    item.getId(), note);
        });
    }


    public PurchaseAfterJunior findOne(SimpleRequest request) {
        String id = request.getJO().getString("ID");
        PurchaseAfterJunior purchaseAfterJunior = purchaseAfterJuniorRepository.findOne(id);
        purchaseAfterJunior.getPurchaseAfterJuniorItems().forEach(item->{
            if (item.getProductQty()!=0) item.setFlag("1");
        });
        return purchaseAfterJuniorRepository.findOne(id);
    }

    /**
     * 拼接交货信息
     */
    private List<Map> makeupPick(JSONObject tempJson, PurchaseAfterJunior purchaseAfterJunior) {
        tempJson.put("id", purchaseAfterJunior.getId());
        tempJson.put("innerBusinessType", purchaseAfterJunior.getInnerBusinessType());
        List<Map> items = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(item -> item.getReturnQty()>0)
                .map(item -> {
                    Map map = new HashMap();
                    map.put("id", item.getId());
                    map.put("cancelQty", item.getReturnQty());
                    return map;
                }).collect(Collectors.toList());
        return items;
    }

    /**
     * 更新申请数量
     */
    public void refreshQty(PurchaseAfterJunior purchaseAfterJunior) {
        purchaseAfterJunior.getPurchaseAfterJuniorItems().forEach(item->{
            item.setProductQty(item.getReturnQty());
        });
    }

    /**
     * 用于前端隐藏明细
     */
    public PurchaseAfterJunior hide(PurchaseAfterJunior purchaseAfterJunior) {
        purchaseAfterJunior.getPurchaseAfterJuniorItems().forEach(item->{
            if (item.getProductQty()!=0) item.setFlag("1");
        });
        return purchaseAfterJunior;
    }

    public boolean checkCompany(PartyRole company,PartyRole supplier,double money) {
        String operation = company.getParty().getCorporate().getOperation().getId();
        if ("001072;001661".contains(operation)) {
            return checkMoney("1001",supplier.getId(),money);
        }else if("001073".equals(operation)) {
            return checkMoney("1007",supplier.getId(),money);
        }else if ("001071".equals(operation)) {
            return checkMoney(company.getId(),supplier.getId(),money);
        }
        return false;
    }


    public boolean checkMoney(String companyId, String supplierId,double money) {
        List<Ledger> ledgers = ledgerRepository.findAll(JpaDsl.toCriteriaByEq("company.id",companyId,"partner.id",supplierId));
        if (ledgers.size() == 0) return false;
        ledgers = ledgers.stream().filter(e->"current_unsettled".equals(e.getLedgerAccount().getId())).collect(Collectors.toList());
        if (ledgers.size() == 0) return false;
        double amount = ledgers.get(0).getAmount();//账款：未清项
        if (amount>money) return true;
        return false;
    }

    /**
     * 生成凭证
     */
    public void createVoucher(Pick pick, PurchaseAfterJunior purchaseAfterJunior) {
        PartyRole supplier = purchaseAfterJunior.getSupplier();
        /**外部供应商**/
        if (!supplier.getParty().getCorporate().inner() || supplier.getParty() == purchaseAfterJunior.getCompany().getParty()) {
            //过滤
            List<PurchaseAfterJuniorItem> juniorItems = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().filter(item -> item.getReturnQty() > 0).collect(Collectors.toList());
            //经销批次
            List<PurchaseAfterJuniorItem> distribution = juniorItems.stream().filter(e -> "distribution".equals(e.getInventoryBatch().getCooperation().getId())).collect(Collectors.toList());
            //代销批次
            List<PurchaseAfterJuniorItem> consignment = juniorItems.stream().filter(e -> "consignment".equals(e.getInventoryBatch().getCooperation().getId())).collect(Collectors.toList());

            if (distribution.size() != 0) createVoucherByInventory(purchaseAfterJunior, distribution, pick, "IM_OWN");
            if (consignment.size() != 0) createVoucherByInventory(purchaseAfterJunior, consignment, pick, "IM_CONSIGN");
        } else { /**内部供应商**/
            /**内部调拨**/
            createCrossTransfer(pick, purchaseAfterJunior);

            /**外部返厂**/
            createPurchaseReturn(pick, purchaseAfterJunior);
        }
    }

    /**内部调拨**/
    private void createCrossTransfer(Pick pick, PurchaseAfterJunior purchaseAfterJunior) {
        PartyRole company = SpringManager.getBean(CrossTransferVoucherBuilder.class).getCompany(purchaseAfterJunior.getCompany());
        PartyRole customer = SpringManager.getBean(CrossTransferVoucherBuilder.class).getCustomer(purchaseAfterJunior.getSupplier());
        Voucher cv = new Voucher();
        cv.setCompany(company);//公司
        cv.setPartner(customer);//合作伙伴
        cv.setScene(purchaseAfterJunior.getScene());
        cv.setOriginBusinessType(pick.getOriginBusinessType());
        cv.setOrigin(pick.getOrigin());
        cv.setSourceBusinessType(pick.getInnerBusinessType());
        cv.setSource(pick.getInnerBusinessKey());
        cv.setInvoiced(true);
        cv.setAccountingMethod(AccountingMethod.AM_PURCHASE);//核算方式
        cv.setInventoryMode(InventoryMode.IM_OWN);//库存方式
        cv.setVoucherType(VoucherType.CROSS_TRANSFER);//凭证类型
        cv.setBusinessType(BusinessType.TRANSFER_ORDER);
        Set<VoucherItem> voucherItems = new HashSet<>();
        purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().forEach(vItem -> {
            VoucherItem vi = new VoucherItem();
            vi.setProduct(vItem.getProduct());
            vi.setUom(vItem.getUom());
            InventoryBatch inventoryBatch = vItem.getInventoryBatch();
            vi.setInventoryBatch(inventoryBatch);
            vi.setSupplier(inventoryBatch.getSupplier());//供应商
            vi.setOriginalSupplier(vItem.getOriginalSupplier());
            double price = inventoryBatch.getUom().computePrice(inventoryBatch.getTaxCostPrice(), vItem.getUom());
            vi.setPriceUnit(price);
            vi.setProductQty(vItem.getProductQty());
            vi.setOriginItemId(String.valueOf(vItem.getId()));
            vi.setSourceItemId(String.valueOf(vItem.getId()));
            vi.setVoucher(cv);
            voucherItems.add(vi);
        });
        cv.setVoucherItems(voucherItems);
        SpringManager.getBean(VoucherService.class).save(cv);
    }

    /**外部返厂**/
    private void createPurchaseReturn(Pick pick, PurchaseAfterJunior purchaseAfterJunior) {
        PartyRole company = SpringManager.getBean(CrossTransferVoucherBuilder.class).getCompany(purchaseAfterJunior.getSupplier());
        purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().collect(groupingBy(vi -> vi.getOriginalSupplier()))
                .forEach((supplier, items) -> {
                    Set<VoucherItem> vitems = new HashSet<>();
                    for (PurchaseAfterJuniorItem item : items) {
                        new BatchMethod<Batch>() {

                            @Override
                            public Iterable<Batch> wrap() {
                                List<InventoryBatch> inventories = inventoryService.findByPurchaseReturnInventory(company, supplier, item.getProduct());
                                return inventoryService.wrapBatch(inventories, item.getUom(), inventory -> inventory.getBalanceQty() - inventory.getFrostQty());
                            }

                            @Override
                            public void succeed(Batch batch, double increment) {
                                InventoryBatch inventoryBatch = (InventoryBatch) batch.getEntity();
                                inventoryService.changeFrostQty(inventoryBatch, item.getUom(), increment, inventoryBatch.getCompany(),
                                        purchaseAfterJunior.getInnerBusinessType(), purchaseAfterJunior.getInnerBusinessKey(),
                                        String.valueOf(item.getId()), "采购退货库存价值评估指定批次增加冻结数量");

                                VoucherItem vi = new VoucherItem();
                                vi.setProduct(item.getProduct());
                                vi.setUom(item.getUom());
                                vi.setTax(inventoryBatch.getTax());
                                vi.setInventoryBatch(inventoryBatch);
                                vi.setSupplier(inventoryBatch.getSupplier());//供应商
                                double price = inventoryBatch.getUom().computePrice(inventoryBatch.getTaxCostPrice(), item.getUom());
                                vi.setPriceUnit(price);
                                vi.setProductQty(-1 * increment);
                                vi.setOriginItemId(String.valueOf(item.getId()));
                                vi.setSourceItemId(String.valueOf(item.getId()));
                                vitems.add(vi);
                            }

                            @Override
                            public void error(double surplus) {
                                throw new RuntimeException("商品：[" + item.getProduct().getId() + "]" + item.getProduct().getName() + " 价值库存数量少 " + surplus + item.getUom().getName() + "！");
                            }
                        }.execute(abs(item.getProductQty()));
                    }

                    vitems.stream().collect(groupingBy(vi -> vi.getInventoryBatch().getCooperation()))
                            .forEach((cooperation, voucherItems) -> {
                                Voucher rpv = new Voucher();
                                rpv.setVoucherType(VoucherType.SUPPLIER_PURCHASE);
                                rpv.setBusinessType(BusinessType.PURCHASE_RETURN);
                                rpv.setCompany(company);
                                rpv.setPartner(supplier);
                                ReflectUtil.copy(pick, rpv, "scene", "originBusinessType", "origin");
                                rpv.setSourceBusinessType(purchaseAfterJunior.getInnerBusinessType());
                                rpv.setSource(purchaseAfterJunior.getInnerBusinessKey());
                                rpv.setInvoiced(true);
                                rpv.setReturned(true);
                                rpv.setInventoryMode(cooperation.getInventoryMode());
                                rpv.setAccountingMethod(cooperation.getAccountingMethod());
                                rpv.setDept(voucherItems.stream().findFirst().orElse(null).getInventoryBatch().getDept());
                                voucherItems.stream().forEach(item -> item.setVoucher(rpv));
                                rpv.setVoucherItems(new HashSet<>(voucherItems));
                                SpringManager.getBean(VoucherService.class).save(rpv);
                            });
                });
    }

    public void createVoucherByInventory(PurchaseAfterJunior purchaseAfterJunior, List<PurchaseAfterJuniorItem> purchaseAfterJuniorItems,
                                         Pick pick, String inventoryMode) {
        Voucher voucher = new Voucher();
        voucher.setScene(purchaseAfterJunior.getScene());
        voucher.setCompany(purchaseAfterJunior.getCompany());//公司
        voucher.setDept(purchaseAfterJunior.getLocation().getDept());//部门
        voucher.setSourceDept(purchaseAfterJunior.getLocation().getDept());//发货部门
        voucher.setPartner(pick.getPartner());//合作伙伴
        voucher.setClerk(purchaseAfterJunior.getApproveUid());
        voucher.setOrigin(pick.getOrigin());//源单据
        voucher.setOriginBusinessType(pick.getOriginBusinessType());//源单据类型
        voucher.setSource(pick.getInnerBusinessKey());//来源单据
        voucher.setSourceBusinessType(pick.getInnerBusinessType());//来源单据类型
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);//核算方式
        voucher.setInventoryMode(inventoryMode);//库存方式
        voucher.setVoucherType(VoucherType.SUPPLIER_PURCHASE);//凭证类型
        voucher.setBusinessType(BusinessType.PURCHASE_RETURN);
        voucher.setContract(purchaseAfterJuniorItems.get(0).getInventoryBatch().getContract());//合同
        voucher.setReturned(true);

        Set<VoucherItem> voucherItems = new HashSet<>();
        for (PurchaseAfterJuniorItem item : purchaseAfterJuniorItems) {
            List<PickItem> pickItems = pick.getPickItems().stream().filter(e -> e.getOriginLine().equals(item.getId())).collect(Collectors.toList());
            if (pickItems.isEmpty()) continue;
            PickItem pickItem = pickItems.get(0);

            VoucherItem voucherItem = new VoucherItem();
            voucherItem.setProductQty(-1*item.getReturnQty());//数量
            voucherItem.setInventoryBatch(item.getInventoryBatch());//价值批次
            voucherItem.setTax(item.getInventoryBatch().getTax());//税种
            voucherItem.setPriceUnit(item.getPriceUnit());//含税单价
            voucherItem.setSupplier(item.getSupplier());//供应商
            voucherItem.setProduct(item.getProduct());//商品
            voucherItem.setUom(item.getUom());//计量单位
            voucherItem.setOwner(purchaseAfterJunior.getCompany());//所属公司
            voucherItem.setOriginItemId(purchaseAfterJunior.getId());//原始单据明细行
            voucherItem.setSourceItemId(String.valueOf(pickItem.getId()));//源单据明细行

            voucherItems.add(voucherItem);
        }
        voucher.setVoucherItems(voucherItems);

        //创建凭证
        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        if ("IM_OWN".equals(voucher.getInventoryMode())) {
            invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
        }

    }

    public void checkQty(PurchaseAfterJunior purchaseAfterJunior) {
        boolean flag = purchaseAfterJunior.getPurchaseAfterJuniorItems().stream().anyMatch(e -> e.getReturnQty() > 0);
        if (!flag) throw new RuntimeException("返厂数量不允许全部为0");
    }

    public List<PurchaseAfterJunior> findByIds(SimpleRequest request) {
        List ids = request.getList();
        List<PurchaseAfterJunior> all = purchaseAfterJuniorRepository.findAll(JpaDsl.toCriteria("id", "IN", ids));
        PrintRecordRepository printRecordRepository = SpringManager.getBean(PrintRecordRepository.class);
        all.forEach(purchaseAfterJunior -> {
                PrintRecord printRecord = printRecordRepository.findBySource(purchaseAfterJunior.getId());
                if (printRecord != null) {
                    printRecord.setPrintNumber(printRecord.getPrintNumber() + 1);
                    printRecordRepository.saveAndFlush(printRecord);
                }else {
                    PrintRecord printRecordNew = new PrintRecord();
                    printRecordNew.setSource(purchaseAfterJunior.getId());
                    printRecordNew.setSourceBusinessType(purchaseAfterJunior.getInnerBusinessType());
                    com.apes.framework.plugin.soe.metadata.BusinessType businessType = SpringManager.getBean(BusinessTypeRepository.class).findOne(purchaseAfterJunior.getInnerBusinessType());
                    printRecordNew.setSourceBusinessTypeName(businessType.getName());
                    printRecordNew.setPrintNumber(1);
                    printRecordRepository.saveAndFlush(printRecordNew);
                }
        });
        return all;
    }
}
